﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics.Contracts;

namespace YasharEl.Infrastructure.ExceptionHandling
{
    public class ReplaceHandler : IExceptionHandler
    {
        #region Fields

        private readonly Type replaceExceptionType;
        private string exceptionMessage;
        private string exceptionMessageResourceKey;

        #endregion

        #region Constructors

        public ReplaceHandler(string exceptionMessage,
            string exceptionMessageResourceKey,
            IMessageTranslator messageTranslator,
            Type replaceExceptionType)
        {
            Contract.Requires<ArgumentNullException>(replaceExceptionType != null, "replaceExceptionType could not be null.");
            Contract.Requires<ArgumentNullException>(messageTranslator != null, "messageTranslator could not be null.");

            this.replaceExceptionType = replaceExceptionType;
            this.exceptionMessage = exceptionMessage;
            this.exceptionMessageResourceKey = exceptionMessageResourceKey;

            if (!string.IsNullOrEmpty(exceptionMessageResourceKey))
            {
                this.exceptionMessage = messageTranslator.Translate(exceptionMessageResourceKey);
            }
        }

        #endregion

        #region Properties

        /// <summary>
        /// The type of exception to replace.
        /// </summary>
        public Type ReplaceExceptionType
        {
            get { return replaceExceptionType; }
        }

        /// <summary>
        /// Gets the message for the new exception.
        /// </summary>
        public string ExceptionMessage
        {
            get { return exceptionMessage; }
        }

        #endregion

        #region IExceptionHandler Implementations

        /// <summary>
        /// Replaces the exception with the configured type for the specified policy.
        /// </summary>
        /// <param name="exception">The original exception.</param>        
        /// <param name="handlingInstanceId">The unique identifier attached to the handling chain for this handling instance.</param>
        /// <returns>Modified exception to pass to the next exceptionHandlerData in the chain.</returns>
        public Exception HandleException(Exception exception, Guid handlingInstanceId)
        {
            return ReplaceException(
                ExceptionUtility.FormatExceptionMessage(ExceptionMessage, handlingInstanceId));
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Replaces an exception with a new exception of a specified type.
        /// </summary>                
        /// <param name="replaceExceptionMessage">The message for the new exception.</param>
        /// <returns>The replaced or "cleansed" exception.  Returns null if unable to replace the exception.</returns>
        private Exception ReplaceException(string replaceExceptionMessage)
        {
            object[] extraParameters = new object[] { replaceExceptionMessage };
            return (Exception)Activator.CreateInstance(replaceExceptionType, extraParameters);
        }

        #endregion
    }
}
